#include <reg52.h>

//DS1302地址定义
#define ds1302_sec_add			0x80		//秒数据地址
#define ds1302_min_add			0x82		//分数据地址
#define ds1302_hr_add			0x84		//时数据地址
#define ds1302_date_add			0x86		//日数据地址
#define ds1302_month_add		0x88		//月数据地址
#define ds1302_day_add			0x8a		//星期数据地址
#define ds1302_year_add			0x8c		//年数据地址
#define ds1302_control_add		0x8e		//控制数据地址
#define ds1302_charger_add		0x90 					 
#define ds1302_clkburst_add		0xbe

#define Addr_Decode_Mode  0x09 //译码模式寄存器地址
#define Addr_Intensity 	  0x0a //亮度控制寄存器地址
#define Addr_Scan_Limit   0x0b //扫描控制寄存器地址
#define Addr_Shutdowm     0x0c //掉电模式寄存器地址
#define Addr_Display_Test 0x0f //显示检测寄存器地址
#define Addr_Digit1       0x01 //数码管位1
#define Addr_Digit2       0x02 //数码管位2
#define Addr_Digit3       0x03 //数码管位3
#define Addr_Digit4       0x04 //数码管位4
#define Addr_Digit5       0x05 //数码管位5
#define Addr_Digit6       0x06 //数码管位6
#define Addr_Digit7       0x07 //数码管位7
#define Addr_Digit8       0x08 //数码管位8



//DS1302引脚定义,可根据实际情况自行修改端口定义
sbit CLK= P1^1;
sbit IO = P1^2;
sbit RST= P1^3;

//定义Max7219端口            
sbit Max7219_pinDIN = P0^0;  
sbit Max7219_pinCS  = P0^1;
sbit Max7219_pinCLK = P0^2;

unsigned char max7219Map[10] = {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b};

//初始时间定义
unsigned char time_buf[8] = {0x20,0x10,0x09,0x14,0x23,0x59,0x50,0x02};//初始时间
unsigned char readtime[14];//当前时间
unsigned char sec_buf=0;  //秒缓存
unsigned char sec_flag=0; //秒标志位

//功能:延时1毫秒
//入口参数:x
//出口参数:无
//说明:晶振为12M
void Delay_xms(unsigned int x)
{
  unsigned int i,j;
  for(i=0;i<x;i++)
    for(j=0;j<112;j++);
}

//DS1302初始化函数
void DS1302_Init(void) 
{
	RST=0;			//RST脚置低
	CLK=0;			//CLK脚置低
}

//向DS1302写入一字节数据
void ds1302_write_byte(unsigned char addr, unsigned char d) 
{
	unsigned char i;
	RST=1;					//启动DS1302总线	
	//写入目标地址：addr
	addr = addr & 0xFE;   //最低位置零，寄存器0位为0时写，为1时读
	for (i = 0; i < 8; i ++) {
		if (addr & 0x01) {
			IO=1;
        } else {
			IO=0;
        }
		CLK=1;      //产生时钟
		CLK=0;
		addr = addr >> 1;
    }
	
	//写入数据：d
	for (i = 0; i < 8; i ++) {
		if (d & 0x01) {
			IO=1;
        } else {
            IO=0;
        }
		CLK=1;    //产生时钟
		CLK=0;
		d = d >> 1;
    }
	RST=0;		//停止DS1302总线
}

//从DS1302读出一字节数据
unsigned char ds1302_read_byte(unsigned char addr) {

	unsigned char i,temp;	
	RST=1;					//启动DS1302总线
	//写入目标地址：addr
	addr = addr | 0x01;    //最低位置高，寄存器0位为0时写，为1时读
	for (i = 0; i < 8; i ++) {
		if (addr & 0x01) {
			IO=1;
        }
		else {
            IO=0;
        }
		CLK=1;
		CLK=0;
		addr = addr >> 1;
    }	
	//输出数据：temp
	for (i = 0; i < 8; i ++) {
		temp = temp >> 1;
		if (IO) {
			temp |= 0x80;
        }
		else {
			temp &= 0x7F;
        }
		CLK=1;
		CLK=0;
    }	
	RST=0;					//停止DS1302总线
	return temp;
}

//向DS302写入时钟数据
void ds1302_write_time(void) 
{
	ds1302_write_byte(ds1302_control_add,   0x00);			//关闭写保护 
	ds1302_write_byte(ds1302_sec_add,       0x80);			//暂停时钟 
	//ds1302_write_byte(ds1302_charger_add,0xa9);	        //涓流充电 
	ds1302_write_byte(ds1302_year_add,      time_buf[1]);	//年 
	ds1302_write_byte(ds1302_month_add,     time_buf[2]);	//月 
	ds1302_write_byte(ds1302_date_add,      time_buf[3]);	//日 
	ds1302_write_byte(ds1302_hr_add,        time_buf[4]);	//时 
	ds1302_write_byte(ds1302_min_add,       time_buf[5]);	//分
	ds1302_write_byte(ds1302_sec_add,       time_buf[6]);	//秒
	ds1302_write_byte(ds1302_day_add,       time_buf[7]);	//周 
	ds1302_write_byte(ds1302_control_add,   0x80);			//打开写保护     
}

//从DS302读出时钟数据
void ds1302_read_time(void)  
{
	time_buf[1]=ds1302_read_byte(ds1302_year_add);		//年 
	time_buf[2]=ds1302_read_byte(ds1302_month_add);		//月 
	time_buf[3]=ds1302_read_byte(ds1302_date_add);		//日 
	time_buf[4]=ds1302_read_byte(ds1302_hr_add);		//时 
	time_buf[5]=ds1302_read_byte(ds1302_min_add);		//分 
	time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒，屏蔽秒的第7位，避免超出59
	time_buf[7]=ds1302_read_byte(ds1302_day_add);		//周 	
}

void WriteMax7219Byte(unsigned char DATA) {
    unsigned char i;
    for (i = 8; i >= 1; i--) {
        Max7219_pinCLK = 0;
        Max7219_pinDIN = DATA & 0x80;
        DATA = DATA << 1;
        Max7219_pinCLK = 1;
    }
}

void WriteMax7219(unsigned char address, unsigned char dat) {
    Max7219_pinCS = 0;
    WriteMax7219Byte(address);           //写入地址，即数码管编号
    WriteMax7219Byte(dat);               //写入数据，即数码管显示数字 
    Max7219_pinCS = 1;
}

void Max7219_Init()
{
	unsigned char addr,i;

	WriteMax7219(Addr_Decode_Mode,  0x00); //译码方式: 不编码
    WriteMax7219(Addr_Intensity,    0x00); //亮度调节: 范围[0x00 ~ 0x0F]
    WriteMax7219(Addr_Scan_Limit,   0x07); //扫描界限: 8个数码管显示
    WriteMax7219(Addr_Shutdowm,     0x01); //关闭模式: 0:关闭 1:开启
    WriteMax7219(Addr_Display_Test, 0x00); //显示测试：1；测试结束，正常显示：0
	
	addr = 0x00;
    for (i = 0; i < 8; i++) {
        addr += 1;
        WriteMax7219(addr, 0x00);  //全部位默认不展示
    }
}

//主函数
void main(void)
{ 
	unsigned char times;
	
    Delay_xms(50);//等待系统稳定
    DS1302_Init(); //DS1302初始化
    Delay_xms(10);
    
	//ds1302_write_time(); //写入初始值
	
	Max7219_Init();

    while(1){
		times++;
		times %=5;
		
        ds1302_read_time();  //读取时间 
        readtime[0]=(time_buf[0]>>4);    //分离出年千位
        readtime[1]=(time_buf[0]&0x0F);  //分离出年百位 
        readtime[2]=(time_buf[1]>>4);    //分离出年十位
        readtime[3]=(time_buf[1]&0x0F);  //分离出年个位 

        readtime[4]=(time_buf[2]>>4);    //分离出月十位
        readtime[5]=(time_buf[2]&0x0F);  //分离出月个位 

        readtime[6]=(time_buf[3]>>4);    //分离出日十位
        readtime[7]=(time_buf[3]&0x0F);  //分离出日个位 

        readtime[8]=(time_buf[4]>>4);    //分离出小时十位
        readtime[9]=(time_buf[4]&0x0F);  //分离出小时个位 
        readtime[10]=(time_buf[5]>>4);   //分离出分钟十位
        readtime[11]=(time_buf[5]&0x0F); //分离出分钟个位
        readtime[12]=(time_buf[6]>>4);   //分离出秒钟十位
        readtime[13]=(time_buf[6]&0x0F); //分离出秒钟个位
		
		if (times >= 4){
			WriteMax7219(Addr_Digit8, max7219Map[readtime[0]]);
			WriteMax7219(Addr_Digit7, max7219Map[readtime[1]]);
			WriteMax7219(Addr_Digit6, max7219Map[readtime[2]]);
			WriteMax7219(Addr_Digit5, max7219Map[readtime[3]]);
			WriteMax7219(Addr_Digit4, max7219Map[readtime[4]]);
			WriteMax7219(Addr_Digit3, max7219Map[readtime[5]]);
			WriteMax7219(Addr_Digit2, max7219Map[readtime[6]]);
			WriteMax7219(Addr_Digit1, max7219Map[readtime[7]]);
		}else{
			WriteMax7219(Addr_Digit8, max7219Map[readtime[8]]);
			WriteMax7219(Addr_Digit7, max7219Map[readtime[9]]);
			WriteMax7219(Addr_Digit6, 0x01);
			WriteMax7219(Addr_Digit5, max7219Map[readtime[10]]);
			WriteMax7219(Addr_Digit4, max7219Map[readtime[11]]);
			WriteMax7219(Addr_Digit3, 0x01);
			WriteMax7219(Addr_Digit2, max7219Map[readtime[12]]);
			WriteMax7219(Addr_Digit1, max7219Map[readtime[13]]); 
		}

        Delay_xms(1000);
    }
}


